package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AuditService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.login.GuiGuLogin;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.atguigu.tingshu.common.constant.SystemConstant.*;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
    @Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private VodService vodService;
	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private AuditService auditService;
	@Autowired
	private UserFeignClient userFeignClient;
	@Autowired
	private AlbumStatMapper albumStatMapper;


	@Override
	public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
		//1.根据所属专辑ID查询专辑信息,得到封面图片,用于后续更新
		Long albumId = trackInfoVo.getAlbumId();
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		if(albumInfo==null){
			log.error("专辑:{}不存在",albumId);
			throw  new GuiguException(404,"专辑不存在");
		}
		//2.新增声音记录
		//2.1将声音vo转为po
		TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
		//2.2给属性赋值
		//2.2.1设置用户ID
		trackInfo.setUserId(userId);
		//2.2.2设置声音序号 要求从1开始递增
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount()+1);
		//2.2.3调用点播平台获取音频详情信息:时长 大小 类型
          TrackMediaInfoVo trackMediaInfoVo =vodService.getTrackMediaInfo(trackInfo.getMediaFileId());
		  if(trackMediaInfoVo != null){
			  trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
			  trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			  trackInfo.setMediaType(trackMediaInfoVo.getType());
		  }
		//2.2.4来源: 用户上传
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
		//2.2.5状态: 待审核
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
		//封面图片 如果未提交使用所属专辑封面则使用默认封面
		String coverUrl = trackInfo.getCoverUrl();
		if(StringUtils.isBlank(coverUrl)){
			trackInfo.setCoverUrl(albumInfo.getCoverUrl());
		}
		//2.3新增声音记录
         trackInfoMapper.insert(trackInfo);
		Long trackId = trackInfo.getId();
		//3. 更新专辑信息: 包含声音数量
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
		albumInfoMapper.updateById(albumInfo);
		//4.新增声音统计记录
         this.saveTrackStat(trackId,SystemConstant.TRACK_STAT_PLAY,0);
         this.saveTrackStat(trackId,SystemConstant.TRACK_STAT_COLLECT,0);
         this.saveTrackStat(trackId,SystemConstant.TRACK_STAT_PRAISE,0);
         this.saveTrackStat(trackId,SystemConstant.TRACK_STAT_COMMENT,0);
		//内容审核---文本审核
		String content=trackInfo.getTrackTitle()+trackInfo.getTrackIntro();
		String suggestion = auditService.auditText(content);
		if("pass".equals(suggestion)){
			trackInfo.setStatus(TRACK_STATUS_PASS);
		} else if ("review".equals(suggestion)) {
			trackInfo.setStatus(TRACK_STATUS_REVIEWING);
		} else if ("block".equals(suggestion)) {
			trackInfo.setStatus(TRACK_STATUS_NO_PASS);
		}
		//6.TODO 对点播平台音频文件进行审核(异步审核)
		String reviewTaskId = auditService.startReviewTask(trackInfo.getMediaFileId());
	     trackInfo.setStatus(TRACK_STATUS_REVIEWING);
		 trackInfo.setReviewTaskId(reviewTaskId);
		 trackInfoMapper.updateById(trackInfo);
	}


	@Override
	public void saveTrackStat(Long trackId, String statType, int statNum) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		trackStat.setStatNum(statNum);
		trackStatMapper.insert(trackStat);
	}

	@Override
	public IPage<TrackListVo> findUserTrackPage(IPage<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {

		return trackInfoMapper.findUserTrackPage(pageInfo,trackInfoQuery);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateTrackInfo(TrackInfoVo trackInfoVo, Long id) {
		//ToDo 文本审核
		//1.判断音频是否修改过
		//1.1 根据声音ID查询声音记录，得到更新前音频ID
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		//对修改后的内容进行审核
		String content=trackInfoVo.getTrackTitle()+trackInfoVo.getTrackIntro();
		String suggestion = auditService.auditText(content);
		if("pass".equals(suggestion)){
			trackInfo.setStatus(TRACK_STATUS_PASS);
		} else if ("review".equals(suggestion)) {
			trackInfo.setStatus(TRACK_STATUS_REVIEWING);
		} else if ("block".equals(suggestion)) {
			trackInfo.setStatus(TRACK_STATUS_NO_PASS);
		}
		String oldMediaFileId = trackInfo.getMediaFileId();
		//1.2 跟参数中提交音频ID进行比较
		String newMediaFileId = trackInfoVo.getMediaFileId();
		if (!oldMediaFileId.equals(newMediaFileId)) {
			//2.如果修改过，获取新提交音频详情
			TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(newMediaFileId);
			if (trackMediaInfo != null) {
				trackInfo.setMediaUrl(trackInfoVo.getMediaUrl());
				trackInfo.setMediaFileId(newMediaFileId);
				trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
				trackInfo.setMediaType(trackMediaInfo.getType());
				trackInfo.setMediaSize(trackMediaInfo.getSize());
			}
			//3.将原来旧文件从点播平台删除
			vodService.deleteTrackMedia(oldMediaFileId);
			//3. ToDo 对修改后音频文件进行内容审核:发起审核任务
			String reviewTaskId = auditService.startReviewTask(trackInfo.getMediaFileId());
			trackInfo.setStatus(TRACK_STATUS_REVIEWING);
			trackInfo.setReviewTaskId(reviewTaskId);
		}
		//4.更新声音记录，审核状态：未通过
		trackInfoMapper.updateById(trackInfo);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void removeTrackInfo(Long id) {
		//根据声音ID查询被删除声音信息,得到声音序号和所属专辑ID
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		Integer orderNum = trackInfo.getOrderNum();
		Long albumId = trackInfo.getAlbumId();
		//根据专辑ID查询专辑信息 更新包含声音数量
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);
		albumInfoMapper.updateById(albumInfo);
		//确保声音被删除后需要保持连续,更新序号
		LambdaUpdateWrapper<TrackInfo> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.setSql("order_num=order_num-1");
		updateWrapper.eq(TrackInfo::getAlbumId,albumId)
				     .gt(TrackInfo::getOrderNum,orderNum);
		trackInfoMapper.update(null,updateWrapper);
		//删除声音信息
		trackInfoMapper.deleteById(id);
		//删除声音统计信息
         trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>()
				               .eq(TrackStat::getTrackId,id));
		//删除云点播文件
		vodService.deleteTrackMedia(trackInfo.getMediaFileId());
	}

	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(IPage<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
		albumTrackListVoPage=trackInfoMapper.findAlbumTrackPage(albumTrackListVoPage,albumId);
		// 动态渲染付费标识
		//根据专辑ID查询专辑信息,得到专辑付费类型以及免费试听的集数
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		Assert.notNull(albumInfo,"专辑{}不存在",albumId);
		String payType = albumInfo.getPayType();
		Integer tracksForFree = albumInfo.getTracksForFree();
		//如果用户未登录 情况一: 且专辑付费类型是VIP免费或付费,将除试听以外其他声音付费标识设置为true
       if(userId ==null){
		   if(ALBUM_PAY_TYPE_VIPFREE.equals(payType) || ALBUM_PAY_TYPE_REQUIRE.equals(payType)){
			   albumTrackListVoPage.getRecords().stream()
					   .filter(i->i.getOrderNum()>tracksForFree)
					   .forEach(i->i.setIsShowPaidMark(true));
		   }
	   }else {
		   // 如果用户已登录 满足以下两种情况需要进一步获取当前页声音购买状态

		   //远程调用用户服务获取用户身份,判断是否是会员(有效期会员)
		   UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
		   Assert.notNull(userInfoVo,"用户{}不存在",userId);
		   Boolean isVip=false;
		   if(userInfoVo.getIsVip().intValue() ==1 && userInfoVo.getVipExpireTime().after(new Date())){
			isVip=true;
		   }
		   //情况二: 如果专辑 付费类型是VIP免费 且当前用户是普通用户 ,满足进一步查询当前页声音购买状态
		   Boolean isNeedCheckPayStatus=false;
		   if(!isVip && ALBUM_PAY_TYPE_VIPFREE.equals(payType)){
			   isNeedCheckPayStatus=true;
		   }
		   //情况三: 如果专辑 付费类型是 付费 当前无论什么用户 ,满足进一步查询当前页声音购买状态
             if(ALBUM_PAY_TYPE_REQUIRE.equals(payType)){
				 isNeedCheckPayStatus=true;
			 }
           //如果满足情况2或者3 调用远程用户服务,得到当前页除试听部分每个声音购买状态
             if(isNeedCheckPayStatus){
            //获取当前页中除了试听意外其他声音ID列表
				 List<Long> needCheckPayStatusTrackIdList = albumTrackListVoPage
						 .getRecords().stream()
						 .filter(i -> i.getOrderNum() > tracksForFree)
						 .map(AlbumTrackListVo::getTrackId)
						 .collect(Collectors.toList());
				 //远程调用用户服务,获取当前页中声音购买状态Map<Long-专辑ID,Integer-购买状态>
				 Map<Long, Integer> payStatusMap =
						 userFeignClient.userIsPaidTrack(userId, albumId, needCheckPayStatusTrackIdList).getData();
				 // 根据响应声音购买状态,动态修改付费标识 购买状态为0的声音付费标识siShowPaidMark全部设置为 true
                  albumTrackListVoPage.getRecords()
						  .stream()
						  .filter(i->i.getOrderNum()>tracksForFree)
						  .forEach(i->i.setIsShowPaidMark(payStatusMap.get(i.getTrackId())==0));
			 }
	   }

		return albumTrackListVoPage;
	}

	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		return trackInfoMapper.getTrackStatVo(trackId);
	}

	@Override
	public void updateTrackStat(TrackStatMqVo mqVo) {
		//1.更新声音统计数值
		trackStatMapper.update(
				null,
				new LambdaUpdateWrapper<TrackStat>()
						.eq(TrackStat::getTrackId, mqVo.getTrackId())
						.eq(TrackStat::getStatType, mqVo.getStatType())
						.setSql("stat_num = stat_num + " + mqVo.getCount())
		);

		//2.如果是"播放"or"评论"还需要更新专辑统计数值
		if (TRACK_STAT_PLAY.equals(mqVo.getStatType())) {
			//更新专辑统计表播放量
			albumStatMapper.update(
					null,
					new LambdaUpdateWrapper<AlbumStat>()
							.eq(AlbumStat::getAlbumId, mqVo.getAlbumId())
							.eq(AlbumStat::getStatType, ALBUM_STAT_PLAY)
							.setSql("stat_num = stat_num + " + mqVo.getCount())
			);
		}
		if (TRACK_STAT_COMMENT.equals(mqVo.getStatType())) {
			//更新专辑统计表评论量
			albumStatMapper.update(
					null,
					new LambdaUpdateWrapper<AlbumStat>()
							.eq(AlbumStat::getAlbumId, mqVo.getAlbumId())
							.eq(AlbumStat::getStatType, ALBUM_STAT_COMMENT)
							.setSql("stat_num = stat_num + " + mqVo.getCount())
			);
		}
	}


}
